package org.example.custom.config;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@Configuration
@EnableConfigurationProperties(DynamicDataSourceProperties.class)  //读取数据源配置
public class DataSourceConfig {

    private final DynamicDataSourceProperties properties;

    //构造方法注入
    public DataSourceConfig(DynamicDataSourceProperties properties) {
        this.properties = properties;
    }

    @Primary
    @Bean
    public DataSource dataSource() {
        Map<Object, Object> targetDataSources = new HashMap<>();

        //遍历并组装yml中数据源
        for (Map.Entry<String, DataSourceProperty> entry : properties.getDatasource().entrySet()) {
            String key = entry.getKey();
            DataSourceProperty prop = entry.getValue();

            HikariConfig hikariConfig = new HikariConfig();
            hikariConfig.setJdbcUrl(prop.getUrl());
            hikariConfig.setUsername(prop.getUsername());
            hikariConfig.setPassword(prop.getPassword());
            hikariConfig.setDriverClassName(prop.getDriverClassName());

            // 设置连接池参数
            hikariConfig.setMaximumPoolSize(prop.getHikari().getMaximumPoolSize());
            hikariConfig.setMinimumIdle(prop.getHikari().getMinimumIdle());
            hikariConfig.setPoolName(prop.getHikari().getPoolName() != null ? prop.getHikari().getPoolName() : key + "-hikari");

            HikariDataSource dataSource = new HikariDataSource(hikariConfig);
            targetDataSources.put(key, dataSource);
        }

        //将组装好的数据源属性封装到自定义数据源中，覆盖原有策略
        MyRoutingDataSource routingDataSource = new MyRoutingDataSource();
        routingDataSource.setTargetDataSources(targetDataSources);
        routingDataSource.setDefaultTargetDataSource(
                targetDataSources.getOrDefault(properties.getPrimary(), targetDataSources.values().iterator().next())
        );

        return routingDataSource;
    }

}
